package com.roads.project.controller;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;

import com.roads.common.constant.Constants;
import com.roads.common.constant.UserConstants;
import com.roads.common.exception.ServiceException;
import com.roads.common.utils.StringUtils;
import com.roads.project.domain.ProBoqMeterage;
import com.roads.project.domain.ProInstitutionDetail;
import com.roads.project.service.IProBoqMeterageService;
import com.roads.project.service.IProInstitutionService;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.roads.common.annotation.Log;
import com.roads.common.core.controller.BaseController;
import com.roads.common.core.domain.AjaxResult;
import com.roads.common.enums.BusinessType;
import com.roads.project.domain.ProBoq;
import com.roads.project.service.IProBoqService;
import com.roads.common.utils.poi.ExcelUtils;
import com.roads.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * 标段清单Controller
 * 
 * @author nhp
 * @date 2021-11-30
 */
@RestController
@RequestMapping("/project/boq")
public class ProBoqController extends BaseController {

    @Autowired
    private IProBoqService proBoqService;

    @Autowired
    private IProBoqMeterageService meterageService;

    @Autowired
    private IProInstitutionService institutionService;

    /**
     * 查询标段清单列表
     */
    @PreAuthorize("@ss.hasPermi('project:boq:list')")
    @GetMapping("/list")
    public TableDataInfo list(ProBoq proBoq) {
        startPage();
        List<ProBoq> list = proBoqService.selectProBoqList(proBoq);
        return getDataTable(list);
    }

    @GetMapping("/listBidBoq")
    public AjaxResult selectLeafNodeList(ProBoq proBoq) {
        List<ProBoq> list = proBoqService.selectLeafNodeList(proBoq);
        return AjaxResult.success(list);
    }

    /**
     * 查询标段清单列表
     */
    @GetMapping("/getTreeList")
    public AjaxResult getTreeList(ProBoq proBoq) {
        List<ProBoq> list = proBoqService.selectProBoqTreeList(proBoq);
        return AjaxResult.success(list);
    }

    /**
     * 查询标段清单大类列表
     * @return 列表
     */
    @GetMapping("/selectBigTypeList")
    public AjaxResult selectBigTypeList(ProBoq proBoq) {
        List<ProBoq> list = proBoqService.selectBigTypeList(proBoq);
        return AjaxResult.success(list);
    }

    /**
     * 查询标段清单列表 排除子项
     */
    @GetMapping("/getTreeListExcludeChild")
    public AjaxResult getTreeListExcludeChild(ProBoq proBoq) {
        List<ProBoq> list = proBoqService.selectProBoqTreeList(proBoq);
        proBoq = proBoqService.selectProBoqById(proBoq.getId());
        Iterator<ProBoq> it = list.iterator();
        while (it.hasNext()) {
            ProBoq b = it.next();
            if (b.getId().equals(proBoq.getId()) ||
                    ArrayUtils.contains(StringUtils.split(b.getAncestors(), ","), proBoq.getBoqCode() + "")) {
                it.remove();
            }
        }
        return AjaxResult.success(list);
    }

    /**
     * 导出标段清单列表
     */
    @Log(title = "工程量清单", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('project:boq:export')")
    @GetMapping("/export")
    public AjaxResult export(ProBoq proBoq) {
        List<ProBoq> list = proBoqService.selectProBoqList(proBoq);
        ExcelUtils<ProBoq> util = new ExcelUtils<ProBoq>(ProBoq.class);
        return util.exportExcel(list, "标段清单数据");
    }

    /**
     * 获取标段清单详细信息
     */
    @PreAuthorize("@ss.hasPermi('project:boq:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(proBoqService.selectProBoqById(id));
    }

    /**
     * 新增标段清单
     */
    @Log(title = "工程量清单", businessType = BusinessType.INSERT)
    @PreAuthorize("@ss.hasPermi('project:boq:add')")
    @PostMapping
    public AjaxResult add(@RequestBody ProBoq proBoq) {
        if (UserConstants.NOT_UNIQUE.equals(proBoqService.checkBoqCodeUnique(proBoq))) {
            return AjaxResult.error("新增清单'" + proBoq.getBoqCode() + "'失败，清单编号已存在");
        }
        proBoq.setCreateBy(getUsername());
        proBoqService.insertProBoq(proBoq);
        return success();
    }

    /**
     * 修改标段清单
     */
    @Log(title = "工程量清单", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('project:boq:edit')")
    @PutMapping
    public AjaxResult edit(@RequestBody ProBoq proBoq) {
        // 修改限制
        // 取出原有清单
        ProBoq oldBoq = proBoqService.selectProBoqById(proBoq.getId());
        // 取出该清单下所有计量清单
        ProBoqMeterage search = new ProBoqMeterage();
        search.setInstitutionCode(oldBoq.getInstitutionCode());
        search.setInstitutionBoqCode(oldBoq.getInstitutionBoqCode());
        List<ProBoqMeterage> meterageList = meterageService.selectModelList(search);
        // priceFlag单价更改标识， amountFlag数量更改标识, 清单编号更改标识
        boolean priceFlag = false;
        boolean amountFlag = false;
        boolean parentFlag = false;
        // 如果单价、数量发生改变
        BigDecimal oldPrice = oldBoq.getPrice() == null ? BigDecimal.ZERO : oldBoq.getPrice();
        BigDecimal newPrice = proBoq.getPrice() == null ? BigDecimal.ZERO : proBoq.getPrice();
        if (oldPrice.compareTo(newPrice) != 0) {
            priceFlag = true;
        }
        BigDecimal oldAmount = oldBoq.getAmount() == null ? BigDecimal.ZERO : oldBoq.getAmount();
        BigDecimal newAmount = proBoq.getAmount() == null ? BigDecimal.ZERO : proBoq.getAmount();
        if (oldAmount.compareTo(newAmount) != 0) {
            amountFlag = true;
        }
        if (!proBoq.getParentCode().equals(oldBoq.getParentCode())) {
            parentFlag = true;
        }
        // 分桩分项工程不可以修改数量限制
        if (amountFlag && meterageList.size() > 1) {
            return error(oldBoq.getBoqCode() + "清单下有多条计量清单,无法修改数量");
        }
        // 查询标段
        ProInstitutionDetail institutionDetail = institutionService.getDetailModelByInnerCode(proBoq.getInstitutionCode());
        for (ProBoqMeterage meterage : meterageList) {
            // 修改单价数量，如果已经计量，无法修改
            if (parentFlag) {
                if (meterage.getAlreadyAmount().compareTo(BigDecimal.ZERO) != 0) {
                    return error(oldBoq.getBoqCode() + "清单已计量,无法修改父项清单");
                }
            }
            if (priceFlag) {
                if (meterage.getAlreadyAmount().compareTo(BigDecimal.ZERO) != 0) {
                    return error(oldBoq.getBoqCode() + "清单已计量,无法修改单价");
                }
            }
            if (amountFlag) {
                BigDecimal cz = newAmount.subtract(oldAmount);
                // 剩余数量重置
                BigDecimal ora  = meterage.getRemainderAmount();
                BigDecimal nra = ora.add(cz);
                if (nra.compareTo(BigDecimal.ZERO) == -1) {
                    return error(oldBoq.getBoqCode() + "修改后数量已经小于剩余可计量数量");
                }
                if (nra.compareTo(BigDecimal.ZERO) == 1) {
                    meterage.setComplete(Constants.NO);
                } else {
                    meterage.setComplete(Constants.YES);
                }
                meterage.setRemainderAmount(nra);
            }
            if (priceFlag || amountFlag) {
                BigDecimal price = proBoq.getPrice() == null ? BigDecimal.ZERO : proBoq.getPrice();
                BigDecimal amount = proBoq.getAmount() == null ? BigDecimal.ZERO : proBoq.getAmount();
                BigDecimal total = amount.multiply(price).setScale(institutionDetail.getDecimalPlace1(), BigDecimal.ROUND_HALF_UP);
                meterage.setTotal(total);
            }
        }
        if (UserConstants.NOT_UNIQUE.equals(proBoqService.checkBoqCodeUnique(proBoq))) {
            return error("修改清单'" + proBoq.getBoqCode() + "'失败，清单编号已存在");
        }
        proBoq.setUpdateBy(getUsername());
        proBoqService.updateProBoq(oldBoq, proBoq, meterageList);
        return success();
    }

    /**
     * 删除标段清单
     */
    @Log(title = "工程量清单", businessType = BusinessType.DELETE)
    @PreAuthorize("@ss.hasPermi('project:boq:remove')")
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        // 删除限制
        for (int i = 0; i < ids.length; i++) {
            // 是否叶子节点，如果不是叶子节点不能删除
            ProBoq boq = proBoqService.selectProBoqById(ids[i]);
            List<ProBoq> childrenList = proBoqService.selectChildrenList(boq.getInstitutionCode(), boq.getBoqCode());
            if (childrenList.size() > 0) {
                return error("选中的工程量清单包含子清单，不允许删除");
            }
            // 如果有计量清单，不允许删除
            ProBoqMeterage search = new ProBoqMeterage();
            search.setInstitutionCode(boq.getInstitutionCode());
            search.setInstitutionBoqCode(boq.getInstitutionBoqCode());
            List<ProBoqMeterage> meterageList = meterageService.selectModelList(search);
            if (meterageList.size() > 0) {
                return error("选中的工程量清单已添加计量清单，不允许删除");
            }
        }
        return toAjax(proBoqService.deleteProBoqByIds(ids));
    }

    /**
     * 清空标段工程量清单
     *
     * @param institutionCode 标段编号
     * @return 结果
     */
    @Log(title = "工程量清单", businessType = BusinessType.CLEAN)
    @PreAuthorize("@ss.hasPermi('project:boq:remove')")
    @PostMapping("/clean")
    public AjaxResult clean(String institutionCode) {
        // 清空限制，如果存在计量清单，不能进行清空操作
        ProBoqMeterage search = new ProBoqMeterage();
        search.setInstitutionCode(institutionCode);
        List<ProBoqMeterage> meterageList = meterageService.selectModelList(search);
        if (meterageList.size() > 0) {
            return error("该标段已添加计量清单，不允许清空");
        }
        proBoqService.clean(institutionCode);
        return success();
    }

    @Log(title = "工程量清单", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('project:boq:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, String institutionCode) throws Exception {
        ExcelUtils<ProBoq> utils = new ExcelUtils<>(ProBoq.class);
        List<ProBoq> list = utils.importExcel(file.getInputStream());
        String userName = getUsername();
        String message = proBoqService.importData(list, userName, institutionCode);
        return AjaxResult.success(message);
    }

    @Log(title = "工程量清单", businessType = BusinessType.SUMMARY)
    @PreAuthorize("@ss.hasPermi('project:boq:summary')")
    @PostMapping("/summary")
    public AjaxResult summary(String institutionCode) {
        // 查看是否存在计量清单
        int count = meterageService.countMeterage(institutionCode);
        if (count == 0) {
            return AjaxResult.error("未发现计量清单，不能进行统计操作");
        }
        return toAjax(proBoqService.summary(institutionCode));
    }

}
